"""
2024-07-30 戴尔服务器管理
"""
import requests
import json
import paramiko
import time
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
requests.packages.urllib3.disable_warnings()
## https://blog.csdn.net/qq_31127143/article/details/124707117  解决paramiko使用invoke_shell交互式命令超时问题

BOARD_USER = 'root'
BOARD_PASSWORD = 'uuerp'
BOARD_ADDR = "https://192.168.0.50/"

# 设置SSH连接参数
hostname = '192.168.0.60'
port = 22  # SSH端口，默认是22
username = 'root'
password = 'asd1234567@'


NAME_SERVER6 = "SERVER6_Win2016_开发"
NAME_SERVER7 = "SERVER7_Win2019_DB"
NAME_演示 = "windows_server_2022_演示"
NAME_实施 = "server8_window2019_实施"
NAME_Server9 = "CentOS 9 Server9"



VMS ={
    "windows_server_2019":(2159305,17),
    NAME_SERVER7:(2100048,20),
    "CentOS 9 AI":(2159302,22),
    NAME_演示:(2109521,23),
    NAME_SERVER6:(2100343,25),
    NAME_实施:(2141481,27),
    NAME_Server9:(2103122,35),
    "CentOS 9 Uuerp":(2159308,36),
    "CentOS 9 Server":(2158943,37)
}

def board_poweron() :
    """
    打开主板电源
    """
    print("打开主板电源...")
    boardstatus = board_powerstatus()
    if boardstatus == 'on' :
        print("主板电源已打开,不需要再次打开")
        return
    url = BOARD_ADDR + 'redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset'
    payload = {'ResetType': 'On'}
    headers = {'content-type': 'application/json'}
    response = requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=(BOARD_USER,BOARD_PASSWORD))


def board_poweroff() :
    """
    关闭主板电源
    注意, 要先检查下虚拟机电源, 如果虚拟机电源还没关, 要先关虚拟机
    """
    try :
        vm_shutdown_all()
    except BaseException as e :
        print(e)
    time.sleep(600)
    url = BOARD_ADDR + 'redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset'
    payload = {'ResetType': 'ForceOff'}
    headers = {'content-type': 'application/json'}
    response = requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=(BOARD_USER,BOARD_PASSWORD))

def board_powerstatus() -> str:
    """
    获取主板电源状态
    """
    response = requests.get(BOARD_ADDR + 'redfish/v1/Systems/System.Embedded.1',verify=False,auth=(BOARD_USER,BOARD_PASSWORD))
    data = response.json()
    ## print data[u'PowerState']
    rs : str = data[u'PowerState']
    rs = rs.lower()
    #rs = ""
    return str(rs)


def vm_execshell(cmd : str) :
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    # 执行命令
    data = None
    
    try :

        # 连接SSH服务器
        ##print("BEFORE CONNECT")
        client.connect(hostname, port, username, password, timeout=10, auth_timeout=10)
        ##print("CONNECTED")
        stdin, stdout, stderr = client.exec_command(cmd, timeout=10)
        ##print("EXECED", cmd)
        # 获取命令输出
        datas = stdout.read().decode()
        ##print("READ", datas)
    except BaseException as e :
        datas = None
    # 关闭连接
    client.close()
    ##print("CLOSED")
    return datas


def vm_poweron(name : str) :
    """
    打开虚拟机电源
    """
    id = VMS[name][1]
    print("POWERING ON ", name)
    cmd = "vim-cmd vmsvc/power.on " + str(id)
    vm_execshell(cmd)

def vm_shutdown(name : str) :
    """
    关闭虚拟机电源
    """
    ## id = VMS[name][0]
    id = 0
    vms = vm_list_active()
    for vm in vms :
        if vm[0] == name :
            id = int(vm[1])
    if id > 0 :
        print("POWERING OFF ", name)
        cmd = "esxcli vm process kill -t=soft -w=" + str(id)
        vm_execshell(cmd)
    else :
        print("未找到ID:", name)
    

def vm_list_active() :
    """
    列出虚拟机列表及状态. 这里是只列出已开机的,FOR关机 
    """
    rs = []
    # 创建SSH客户端
    cmd = 'esxcli vm process list'
    datas = vm_execshell(cmd)
    if datas is None :
        datas = ""

    lines = datas.split('\n')
    cnt = len(lines)
    for i in range(0, cnt - 1) :
        data = lines[i]
        # if data.find('World ID') != -1 :
        #      print(data)
        if i < cnt - 2 and lines[i + 1].find('World ID') != -1 :
            servername = lines[i]
            wordid = lines[i + 1][13:]
            displayname = lines[i+5][16:]
            print(servername, wordid)
            rs.append((servername, wordid))
            i = i + 7
    return rs



def vm_list_active_tolist() -> list[str]:
    """
    列出虚拟机列表及状态. 这里是只列出已开机的,FOR关机 
    """
    rs = []
    # 创建SSH客户端
    cmd = 'esxcli vm process list'
    datas = vm_execshell(cmd)
    if datas is None :
        datas = ""

    lines = datas.split('\n')
    cnt = len(lines)
    for i in range(0, cnt - 1) :
        data = lines[i]
        # if data.find('World ID') != -1 :
        #      print(data)
        if i < cnt - 2 and lines[i + 1].find('World ID') != -1 :
            servername = lines[i]
            wordid = lines[i + 1][13:]
            displayname = lines[i+5][16:]
            #print(servername, wordid)
            rs.append(servername)
            i = i + 7
    return rs


def vm_list_closed() :
    """
    列出已关闭的虚拟机, FOR开机
    """
    rs = []
    cmd = 'vim-cmd vmsvc/getallvms'
    datas = vm_execshell(cmd)
    ## print(datas)
    if datas is None :
        datas = ""
    return rs


def vm_find(name) :
    """
    根据虚拟机名称查找虚拟机
    """
    return VMS[name]


def vm_poweron_all() :
    """
    打开所有虚拟机
    """
    actives = vm_list_active()

    for k, v in VMS.items() :
        find = False
        for a in actives :
            name = a[0]
            if name == k :
                find = True
                break
        if not find :
            vm_poweron(k)
            ## time.sleep(20)
            while True :
                vms = vm_list_active_tolist()
                if k in vms :
                    break
                time.sleep(1)
            

        else :
            print(k, "已经开机,不需要再次开机")


def vm_poweron_normal() :
    """
    打开工作中要打开的虚拟机
    """
    i = 600
    while i > 0 :
        try :
            print("尝试启动虚拟机...")
            while True :
                vm_poweron(NAME_SERVER7)
                time.sleep(1)
                i -= 1
                vms = vm_list_active_tolist()
                if NAME_SERVER7 in vms :
                    break
                

            while True :
                vm_poweron(NAME_演示)
                time.sleep(1)
                i -= 1
                vms = vm_list_active_tolist()
                if NAME_演示 in vms :
                    break
            while True :
                vm_poweron(NAME_SERVER6)
                time.sleep(1)
                i -= 1
                vms = vm_list_active_tolist()
                if NAME_SERVER6 in vms :
                    break
            while True :
                vm_poweron(NAME_实施)
                time.sleep(1)
                i -= 1
                vms = vm_list_active_tolist()
                if NAME_实施 in vms :
                    break
            while True :
                vm_poweron(NAME_Server9)
                time.sleep(1)
                i -= 1
                vms = vm_list_active_tolist()
                if NAME_Server9 in vms :
                    break
            break
        except Exception as e :
            print("启动虚拟机失败, 尝试剩余秒数/次数:", i)
            print(e)
            time.sleep(1)
        i -= 1


def vm_shutdown_all() :
    """
    关闭所有虚拟机
    """
    actives = vm_list_active()
    for a in actives :
        # time.sleep(10)
        while True :
            vm_shutdown(a[0])
            time.sleep(1)
            vms = vm_list_active_tolist()
            if a[0] not in vms :
                break
            time.sleep(1)




# if __name__ == '__main__' :
#     ## print(bord_powerstatus())
#     activevms = vm_list_active()
#     print(activevms)
#     ## vm_shutdown(2158407)
#     vm_list_closed()
#     ## vm_poweron(37)
#     ## vm_poweron_all()
#     ##vm_shutdown_all()